module timer_top(
    // Parallel TIMER Interface
    wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_o, wb_dat_i, wb_sel_i, wb_we_i,
    wb_stb_i, wb_cyc_i, wb_ack_o,
    
    timer_int
);

//
// Default address and data bus width
//
parameter dw = 32;   // number of data-bits

//
// TIMER interface
//
input   wb_clk_i;
input   wb_rst_i;
input   [31:0] wb_adr_i;
output reg [dw-1:0] wb_dat_o;
input   [dw-1:0] wb_dat_i;
input   [3:0] wb_sel_i;
input   wb_we_i;
input   wb_stb_i;
input   wb_cyc_i;
output reg wb_ack_o;
output timer_int;


reg [1:0] waitstate;

// Wishbone read/write accesses
wire wb_acc = wb_cyc_i & wb_stb_i;    // WISHBONE access
wire wb_wr  = wb_acc & wb_we_i;       // WISHBONE write access
wire wb_rd  = wb_acc & !wb_we_i;      // WISHBONE read access


//定时器设计：
//定时器寄存器timer_ctrl\timer_count\timer_value
// [0]: timer enable 1  
// [1]: timer int enable 1  
// [2]: timer int pending, write 0 to clear it 
/*中断的等待(pending)状态，有效时表示表示定时器中断正在等待(pending)*/  

// addr offset: 0x00  
reg[31:0] timer_ctrl;  
  
// timer current count, read only  
// addr offset: 0x04  
reg[31:0] timer_count;  
  
// timer expired value  
// addr offset: 0x08  
reg[31:0] timer_value;  //设置阈值

//寄存器地址规划  
localparam REG_CTRL = 4'h0; //定时器使能 定时器中断使能   
localparam REG_COUNT = 4'h4; //定时器计数器（只读类型）
localparam REG_VALUE = 4'h8; //设置阈值

assign timer_int = timer_ctrl[2];
//寄存器数据读取
always @(posedge wb_clk_i ) begin
	if( wb_rst_i == 1'b1 ) begin //复位信号
		waitstate <= 2'h0;
		wb_ack_o <= 1'b0;
		timer_value <= 32'b0;
		timer_ctrl <= 32'b0;
	end else if(wb_acc == 1'b0) begin //无访问状态
		waitstate <= 2'h0;
		wb_ack_o <= 1'b0;
		wb_dat_o <= 32'h00000000;
		if ( timer_count == timer_value && timer_ctrl[1] == 1'b1) begin
			timer_ctrl <= timer_ctrl | 32'b0100;
		end
	end else if(waitstate == 2'h0) begin //开始状态
		wb_ack_o <= 1'b0;
		if(wb_acc) begin
			waitstate <= waitstate + 2'h1;
		end
		if ( timer_count == timer_value && timer_ctrl[1] == 1'b1) begin
			timer_ctrl <= timer_ctrl | 32'b0100;
		end
	end else begin
		waitstate <= waitstate + 4'h1;
		wb_ack_o <= 1'b0;
		if(waitstate == 2'h1) begin
			if (wb_wr == 1'b1) begin
				if({10'b0000000000,wb_adr_i[21:2],2'b00} == REG_CTRL) begin
					timer_ctrl <= wb_dat_i;
				end else if({10'b0000000000,wb_adr_i[21:2],2'b00} == REG_VALUE) begin
					timer_value <= wb_dat_i;
				end else;
			end else if (wb_rd == 1'b1)begin
				if({10'b0000000000,wb_adr_i[21:2],2'b00} == REG_CTRL) begin
					wb_dat_o <= timer_ctrl;
				end else if({10'b0000000000,wb_adr_i[21:2],2'b00} == REG_COUNT) begin
					wb_dat_o <= timer_count;
				end else if({10'b0000000000,wb_adr_i[21:2],2'b00} == REG_VALUE) begin
					wb_dat_o <= timer_value;
				end else begin
					wb_dat_o <= 32'b0;
				end
				if ( timer_count == timer_value && timer_ctrl[1] == 1'b1) begin
					timer_ctrl <= timer_ctrl | 32'b0100;
				end
			end 
		end else if(waitstate == 2'h2) begin//结束处理
			if ( timer_count == timer_value && timer_ctrl[1] == 1'b1) begin
				timer_ctrl <= timer_ctrl | 32'b0100;
			end
			wb_ack_o <= 1'b1;	
		end else if(waitstate == 2'h3) begin
			if ( timer_count == timer_value && timer_ctrl[1] == 1'b1) begin
				timer_ctrl <= timer_ctrl | 32'b0100;
			end
			wb_ack_o <= 1'b0;
			waitstate <= 2'h0;
		end
	end
end
//计时器处计时
always @ (posedge wb_clk_i) begin
	if ( wb_rst_i == 1'b1 ) begin
		timer_count <= 32'b0;
	end else if ( timer_count == timer_value) begin
		timer_count <= 32'b0;
	end else if (timer_ctrl[0] == 1'b1) begin
		timer_count <= timer_count + 32'b1;
	end else begin
		timer_count <= 32'b0;
	end
end

endmodule
